<?php

namespace mongrove;

/**
 *
 * The AtomicIntegerField is a container for integer values.
 * Unlike the IntegerField all set actions to the AtomicIntegerField
 * are perceived as deltas to the previous value.
 *
 * @author Michiel Hakvoort <michiel@hakvoort.it>
 * @author Gido Hakvoort <gido@hakvoort.it>
 *
 */
class AtomicIntegerField extends IntegerField {

    protected $delta;
    
    /**
     *
     * Define a new IntegerField
     *
     * @param int $default The default value of this field
     */
    public function __construct($default = 0) {
        parent :: __construct();

        if(($newDefault = filter_var($default, FILTER_VALIDATE_INT)) === false) {
            throw new \Exception("{$default} is not a valid value for this field.");
        }
        
        $this->value = $newDefault;
        
        $this->delta = 0;
    }

    /**
     * (non-PHPdoc)
     * @see src/mongrove.SimpleField::setValueImpl()
     */
    protected function setValueImpl($value) {
        if($this->value === $value) {
            return false;
        }

        $options = array();

        if($this->minimum !== null) {
            $options['options']['min_range'] = $this->minimum;
        }

        if($this->maximum !== null) {
            $options['options']['max_range'] = $this->maximum;
        }

        if(($newValue = filter_var($value, FILTER_VALIDATE_INT, $options)) === false) {
            throw new \Exception("{$value} is not a valid value for this field.");
        }

        /*
         * Store the delta and copy the value
         */
        $this->delta += $newValue - $this->value;
        $this->value = $newValue;

        return true;
    }

    /**
    * (non-PHPdoc)
    * @see src/mongrove.Field::getMutations()
    */
    public function getMutations($path = null, $name = null) {
        $mutations = array();
    
        if($this->isModified() && $this->delta !== 0) {
            $path === null ?: $path .= '.';
            $mutations[] = array(Command :: OP_INC => array("{$path}{$name}" => $this->delta));
        }
    
        return $mutations;
    }

    public function clean() {
        parent :: clean();

        $this->delta = 0;
    }
}
